


namespace GameServer.ShootingGame.RenderableClasses
{
    using System.Collections.Generic;
    using System.Drawing;
    using GameServer.ShootingGame.Physics.CollisionReactionClasses.Base;
    using System;

    public class GameObject : IRendered
    {
        public int id;
        public double xPosition;
        public double yPosition;
        public double relativeCollidablePointX;
        public double relativeCollidablePointY;
        public double width;
        public double height;
        protected RectangleF collidablePart;
        private double facing;
        public List<AttachableObject> attachments;
        public bool isInvulnerable;
        public bool canRegisterOrdinanceImpact;
        private int hitPoints;
        private int hitPointMax;
        protected bool isExpired;
        public CollisionEffects collisionEffects;
        protected bool isReadyForUpdate;
        private GamePlayManager gamePlayManager;
        public bool isHitDetectionEnabled;

        public GameObject()
            : this(0, 0)
        {
        }

        public GameObject(double xPos, double yPos)
        {
            this.xPosition = xPos;
            this.yPosition = yPos;
            facing = 0;
            isInvulnerable = true;
            canRegisterOrdinanceImpact = false;
            hitPoints = 1;
            hitPointMax = 1;
            relativeCollidablePointX = 0;
            relativeCollidablePointY = 0;
            width = 1;
            height = 1;
            attachments = null;
            isHitDetectionEnabled = false;
        }

        virtual public void Update()
        {
            if (isExpired)
                return;
        }

        virtual public void AddAttachment(AttachableObject attch)
        {
            if (attch.AttachedTo == this)
            {
                if (attachments == null)
                    attachments = new List<AttachableObject>();
                attachments.Add(attch);
            }
        }

        virtual public void RemoveAttachment(AttachableObject attch)
        {
            if (attch.AttachedTo == this)
            {
                attachments.Remove(attch);
                attch.AttachedTo = null;
            }
        }

        /// <summary>
        /// Adds the object to the update list. Returns false if the object is already on the list.
        /// </summary>
        virtual public bool AddObject()
        {
            if (!gamePlayManager.MiscList.Contains(this))
            {
                gamePlayManager.MiscList.Add(this);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Removes the object from the update list. Returns false if the object was not on the update list.
        /// </summary>
        /// <returns></returns>
        virtual public bool RemoveObject()
        {
            if (gamePlayManager.MiscList.Contains(this))
            {
                gamePlayManager.MiscList.Remove(this);
                return true;
            }
            return false;
        }

        public double Facing
        {
            get
            {
                return facing;
            }
            set
            {
                if (value >= 360)
                {
                    value = value % 360;
                }
                else
                    if (value < 0)
                    {
                        while (value < 0)
                            value += 360;
                    }
                facing = value;
            }
        }

        virtual public bool IsExpired
        {
            get
            {
                return isExpired;
            }
            set
            {
                if (isExpired == value)
                    return;
                isExpired = value;
                if (isExpired)
                    RemoveObject();
            }

        }


        public int HitPoints
        {
            get
            {
                return hitPoints;
            }
            set
            {
                hitPoints = value;
                if (hitPoints > hitPointMax)
                    hitPoints = hitPointMax;
                else
                    if (hitPoints <= 0)
                    {
                        hitPoints = 0;
                        isExpired = true;
                    }
            }
        }

        public int HitPointMax
        {
            get
            {
                return hitPointMax;
            }
            set
            {
                double ratio = value / hitPointMax;
                hitPointMax = value;
                HitPoints = (int)(hitPoints * ratio);
            }
        }

        virtual public RectangleF CollidablePart
        {
            get
            {
                if (collidablePart == null)
                {
                    collidablePart = new RectangleF(Convert.ToSingle(xPosition + relativeCollidablePointX * Math.Cos(facing) - width / 2.0), Convert.ToSingle(yPosition + relativeCollidablePointY * Math.Sin(facing) - height / 2.0), Convert.ToSingle(width), Convert.ToSingle(height));
                }
                else
                {
                    collidablePart.X = Convert.ToSingle(xPosition + relativeCollidablePointX * Math.Cos(facing) - width / 2.0);
                    collidablePart.Y = Convert.ToSingle(yPosition + relativeCollidablePointY * Math.Sin(facing) - height / 2.0);
                    collidablePart.Width = Convert.ToSingle(width);
                    collidablePart.Height = Convert.ToSingle(height);
                }
                return collidablePart;
            }
            set
            {
                collidablePart = value;
            }
        }

        virtual public GamePlayManager GamePlayManager
        {
            get { return gamePlayManager; }
            set
            {
                gamePlayManager = value;

            }
        }


        /// <summary>
        /// ReadOnly. Returns whether the GameObject has been marked for update yet.
        /// </summary>
        virtual public bool IsReadyForUpdate
        {
            get
            {
                return isReadyForUpdate;
            }
        }

        /// <summary>
        /// Adds the GameObject to the update list. Call this method to activate a GameObject after setting its properties.
        /// Returns false if this GameObject is already marked for update.
        /// </summary>
        /// <returns></returns>
        virtual public bool StartUpdate()
        {
            if (isReadyForUpdate)
                return false;
            else
            {
                isReadyForUpdate = true;
                AddObject();
                return true;
            }
        }

        /// <summary>
        /// Makes isReadyForUpdate as false and removes this GameObject from the update list.
        /// Returns false if the object is already unmarked.
        /// </summary>
        /// <returns></returns>
        virtual public bool StopUpdate()
        {
            if (!isReadyForUpdate)
                return false;
            else
            {
                isReadyForUpdate = false;
                RemoveObject();
                return true;
            }
        }
    }
}
